package org.apache.cxf.interceptor;

/**
 * <p><em>Created on 2022/4/8 2:05 下午</em></p>
 *
 * @author fuzhongtang
 * @since 1.0.1
 */

import org.apache.cxf.helpers.IOUtils;
import org.apache.cxf.interceptor.Fault;
import org.apache.cxf.io.CachedOutputStream;
import org.apache.cxf.message.Message;
import org.apache.cxf.phase.AbstractPhaseInterceptor;
import org.apache.cxf.phase.Phase;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;

public class WsOutInterceptor extends AbstractPhaseInterceptor<Message> {
    private final static Logger logger = LoggerFactory.getLogger(WsOutInterceptor.class);

    public WsOutInterceptor() {
        // 拦截器在调用方法之前拦截SOAP消息
        //这儿使用receive，接收的意思
        super(Phase.RECEIVE);
    }

    @Override
    public void handleMessage(Message message) throws Fault {
        InputStream  inputStream = message.getContent(InputStream.class);
        CachedOutputStream bosLog = new CachedOutputStream();
        CachedOutputStream bosNew = null;
        try {
            try {
                IOUtils.copy(inputStream, bosLog);
                bosLog.flush();
                recordLog("接收到报文：",bosLog.getInputStream());
                bosNew = updateMesage(bosLog);
                if(null == bosNew || bosNew.size()<=0){
                    bosNew = bosLog;
                }

                message.setContent(InputStream.class, bosNew.getInputStream());

            } catch (IOException e) {
                e.printStackTrace();
            }
        }finally {
            try {
                bosLog.close();
                if (null != bosNew){
                    bosNew.close();
                }
                inputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 更新不合法报文
     * @param bosUpdate
     * @return
     */
    private CachedOutputStream updateMesage(CachedOutputStream bosUpdate){
        boolean  isChange = false;
        boolean  isAlreadyChange = false;
        CachedOutputStream bos = new CachedOutputStream();
        if (bosUpdate != null) {
            try {
                String str = IOUtils.toString(bosUpdate.getInputStream());
                str = str.trim();
                if(str.isEmpty()){
                    return null;
                }
                if(str.indexOf("<?")>0 || str.indexOf("?>")>0){
                    isChange = true;
                }
                if(isChange){
                    int tagS = str.indexOf("<?");
                    int tagE = str.indexOf("?>");
                    String tmp = str.substring(tagS,tagE+2);
                    str = str.replace(tmp,"");
                    isAlreadyChange=true;
                }
                if(str.indexOf("<![CDATA[")<0){
                    isChange = true;
                }
                if(isChange){
                    str = str.replace("<xmlMessage>","<![CDATA[<xmlMessage>");
                    str = str.replace("</xmlMessage>","</xmlMessage>]]>");
                    isAlreadyChange=true;
                }
                if(isAlreadyChange){
                    // 替换后的报文
                    try(InputStream ism = new ByteArrayInputStream(str.getBytes(StandardCharsets.UTF_8))){
                        IOUtils.copy(ism, bos);
                        recordLog("处理后报文："+str,null);
                    }
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return bos;
    }
    private void recordLog(String title,InputStream inputStream) throws IOException {
        String str = title;
        if (inputStream != null) {
            try {
                str = str+IOUtils.toString(inputStream);
                str = str.trim();
                if(str.isEmpty()){
                    return;
                }
            } catch (IOException e) {
                e.printStackTrace();
            }finally {
                inputStream.close();
            }
        }
        logger.info(str);
    }
    private static ByteArrayOutputStream cloneInputStream(InputStream input) {
        try {
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            byte[] buffer = new byte[1024];
            int len;
            while ((len = input.read(buffer)) > -1) {
                baos.write(buffer, 0, len);
            }
            baos.flush();
            return baos;
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }
    }
}
